package edu.tec.mty.core.modules.models;

import edu.tec.mty.core.modules.Self;
import edu.tec.mty.extras.Vector2D;

public class Ball {

	private Ball boundTo = null;
	private double x = 0.0, y = 0.0;
	private double vx = 0.0, vy = 0.0;
	private long step = 0;
	private boolean viewed = false;
	private int ID = 0;
	private int countToDeath = 0;
	private boolean onEntryRegion = false;
	
	//Constructor for ball initialization
	public Ball() {
		this.step = 0;
		this.viewed = false;
	}
	
	public Ball(Ball ball) {
		this.viewed = ball.isViewed();
		this.x = ball.getCurrentPosition().getX();
		this.y = ball.getCurrentPosition().getY();
		this.vx = ball.getVelocity().getXComponent();
		this.vy = ball.getVelocity().getYComponent();
		this.boundTo = ball.getBound();
	}
	
	//Constructor for coach and trainer
	public Ball(Position position, Ball lastModel, long step) {
		this.boundTo = lastModel;
		this.x = position.getX();
		this.y = position.getY();
		this.step = step;
		this.viewed = true;
	}
	
	//Constructor for empty ball
	public Ball(long step) {
		this.step = step;
		this.viewed = false;
	}
	
	//Constructor beta for players
	public Ball(Position agentPosition, 
				long step, 
				double direction, 
				double distance, 
				double distChange, 
				double dirChange) {
		double sourceAngle = agentPosition.getBodyAngle() + agentPosition.getNeckAngle() + direction;
		if (sourceAngle > 180.0) {
			sourceAngle -= 360.0;
		}
		if (sourceAngle < -180.0) {
			sourceAngle += 360.0;
		}
		double erx = Math.cos(Math.toRadians(sourceAngle));
		double ery = Math.sin(Math.toRadians(sourceAngle));
		double erxm = (180.0 * erx) / (Math.PI * distance);
		double erym = (180.0 * ery) / (Math.PI * distance);
		double vry = (distChange * erym + dirChange * erx) / (ery * erym + erx * erxm);
		double vrx = (distChange - ery * vry) / erx;
		double prx = distance * erx;
		double pry = distance * ery;
		double vxo = Self.AMOUNT_OF_SPEED * Math.cos(Math.toRadians(Self.DIRECTION_OF_SPEED));
		double vyo = Self.AMOUNT_OF_SPEED * Math.sin(Math.toRadians(Self.DIRECTION_OF_SPEED));
		this.vx = vxo + vrx;
		this.vy = vyo + vry;
		this.x = agentPosition.getX() + prx;
		this.y = agentPosition.getY() + pry;
		this.step = step;
		this.viewed = true;
	}
	
	public void setID(int ID) {
		this.ID = ID;
	}
	
	public int getID() {
		return this.ID;
	}
	
	public boolean onEntryRegion() {
		return this.onEntryRegion;
	}
	
	public int getCountToDeath() {
		return this.countToDeath;
	}
	
	public boolean isViewed() {
		return this.viewed;
	}
	
	public Vector2D getVelocity() {
		return new Vector2D(this.vx, this.vy);
	}
	
	public Position getCurrentPosition() {
		return new Position(this.x, this.y);
	}
	
	public Position getPredictedPosition(int cycles) {
		return new Position(this.x + (double)cycles * this.vx, this.y + (double)cycles * this.vy);
	}
	
	public long getGlobalTime() {
		return this.step;
	}
	
	public Ball getBound() {
		return this.boundTo;
	}
	
	public void bindTo(Ball ball) {
		if (!ball.isViewed()) {
			this.countToDeath = ball.getCountToDeath() + 1;
		}
		this.boundTo = ball;
	}
	
	public void unbind() {
		this.boundTo = null;
	}
	
	public Ball clone() {
		return new Ball(this);
	}
	
	//Test
	
	/*public static void main(String[] args) {
		Position playerPosition = new Position(0.0, 0.0, 0.0, 0.0);
		Ball ball = new Ball(-45.0, 10.0, playerPosition, new Ball(), 0);
		System.out.println("x: " + ball.getPosition().getX() + " y: " + ball.getPosition().getY());
		System.out.println("angle: " + playerPosition.getAngleFromBodyTo(ball.getPosition()));
	}/**/
	
}
